added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / typeexpression.cs
blob2f105065e2beba5302916b1fec9683da6bf26dd5
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
18 using System;
19 using System.Collections;
20 using System.Reflection;
21 using System.Reflection.Emit;
22 using System.Text;
24 internal sealed class TypeExpression : AST{
25 internal AST expression;
26 internal bool isArray;
27 internal int rank;
28 private bool recursive;
29 private IReflect cachedIR;
31 internal TypeExpression(AST expression)
32 : base(expression.context) {
33 this.expression = expression;
34 this.isArray = false;
35 this.rank = 0;
36 this.recursive = false;
37 this.cachedIR = null;
38 if (expression is Lookup){
39 String name = expression.ToString();
40 Object ptype = Globals.TypeRefs.GetPredefinedType(name);
41 if (ptype != null)
42 this.expression = new ConstantWrapper(ptype, expression.context);
46 internal override Object Evaluate(){
47 return this.ToIReflect();
50 internal override IReflect InferType(JSField inference_target){
51 return this.ToIReflect();
54 // has to be called after partially evaluate
55 internal bool IsCLSCompliant(){
56 Object value = this.expression.Evaluate();
57 return TypeExpression.TypeIsCLSCompliant(value);
60 internal override AST PartiallyEvaluate(){
61 if (this.recursive){
62 if (this.expression is ConstantWrapper) return this;
63 this.expression = new ConstantWrapper(Typeob.Object, this.context);
64 return this;
66 Member member = this.expression as Member;
67 if (member != null){
68 //Dealing with a qualified name. See if there is a type/class with such a name, bypassing normal scope lookup.
69 Object type = member.EvaluateAsType();
70 if (type != null){
71 this.expression = new ConstantWrapper(type, member.context);
72 return this;
75 this.recursive = true;
76 this.expression = this.expression.PartiallyEvaluate();
77 this.recursive = false;
78 if (this.expression is TypeExpression)
79 return this;
80 //Make sure that the expression represents a Type
81 Type t = null;
82 if (this.expression is ConstantWrapper){
83 Object val = this.expression.Evaluate();
84 if (val == null){
85 this.expression.context.HandleError(JSError.NeedType);
86 this.expression = new ConstantWrapper(Typeob.Object, this.context);
87 return this;
89 t = Globals.TypeRefs.ToReferenceContext(val.GetType());
90 Binding.WarnIfObsolete(val as Type, this.expression.context);
91 }else{
92 if (this.expression.OkToUseAsType())
93 t = Globals.TypeRefs.ToReferenceContext(this.expression.Evaluate().GetType());
94 else{
95 this.expression.context.HandleError(JSError.NeedCompileTimeConstant);
96 this.expression = new ConstantWrapper(Typeob.Object, this.expression.context);
97 return this;
100 if (t == null || (t != Typeob.ClassScope && t != Typeob.TypedArray && !Typeob.Type.IsAssignableFrom(t))){
101 this.expression.context.HandleError(JSError.NeedType);
102 this.expression = new ConstantWrapper(Typeob.Object, this.expression.context);
104 return this;
107 internal IReflect ToIReflect(){
108 if (!(this.expression is ConstantWrapper))
109 this.PartiallyEvaluate();
110 IReflect result = this.cachedIR;
111 if (result != null) return result;
112 Object value = this.expression.Evaluate();
113 if (value is ClassScope || value is TypedArray || this.context == null)
114 result = (IReflect)value;
115 else
116 result = Convert.ToIReflect((Type)value, this.Engine);
117 if (this.isArray)
118 return this.cachedIR = new TypedArray(result, this.rank);
119 else
120 return this.cachedIR = result;
123 internal Type ToType(){
124 if (!(this.expression is ConstantWrapper))
125 this.PartiallyEvaluate();
126 Object value = this.expression.Evaluate();
127 Type result = null;
128 if (value is ClassScope)
129 result = ((ClassScope)value).GetTypeBuilderOrEnumBuilder();
130 else if (value is TypedArray)
131 result = Convert.ToType((TypedArray)value);
132 else
133 result = Globals.TypeRefs.ToReferenceContext((Type)value);
134 if (this.isArray){
135 return Convert.ToType(TypedArray.ToRankString(this.rank), result);
136 }else
137 return result;
140 internal override void TranslateToIL(ILGenerator il, Type rtype){
141 this.expression.TranslateToIL(il, rtype);
144 internal override void TranslateToILInitializer(ILGenerator il){
145 this.expression.TranslateToILInitializer(il);
148 internal static bool TypeIsCLSCompliant(Object type){
149 if (type is ClassScope)
150 return ((ClassScope)type).IsCLSCompliant();
151 else if (type is TypedArray){
152 Object et = ((TypedArray)type).elementType;
153 if (et is TypedArray || (et is Type && ((Type)et).IsArray)) return false;
154 return TypeExpression.TypeIsCLSCompliant(et);
155 }else{
156 Type t = (Type)type;
157 if (t.IsPrimitive)
158 if (t == Typeob.Boolean ||
159 t == Typeob.Byte ||
160 t == Typeob.Char ||
161 t == Typeob.Double ||
162 t == Typeob.Int16 ||
163 t == Typeob.Int32 ||
164 t == Typeob.Int64 ||
165 t == Typeob.Single)
166 return true;
167 else
168 return false;
169 else{
170 if (t.IsArray){
171 Type et = t.GetElementType();
172 if (et.IsArray) return false;
173 return TypeExpression.TypeIsCLSCompliant(t);
175 Object[] attr = CustomAttribute.GetCustomAttributes(t, typeof(CLSCompliantAttribute), false);
176 if (attr.Length > 0)
177 return ((CLSCompliantAttribute)attr[0]).IsCompliant;
178 else{
179 Module m = t.Module;
180 attr = CustomAttribute.GetCustomAttributes(m, typeof(CLSCompliantAttribute), false);
181 if (attr.Length > 0)
182 return ((CLSCompliantAttribute)attr[0]).IsCompliant;
183 else{
184 Assembly a = m.Assembly;
185 attr = CustomAttribute.GetCustomAttributes(a, typeof(CLSCompliantAttribute), false);
186 if (attr.Length > 0)
187 return ((CLSCompliantAttribute)attr[0]).IsCompliant;
188 else
189 return false;